home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 April: Mac OS SDK / Dev.CD Apr 96 SDK / Dev.CD Apr 96 SDK1.toast / Development Kits (Disc 1) / OpenDoc / Sample Code / CALib & You… / Source / CALib / ODSource / Implementation / ODPrcs.cpp < prev    next >
Encoding:
Text File  |  1995-12-07  |  51.6 KB  |  1,864 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        ODPrcs.cpp
  3.  
  4.     Contains:    OpenDoc Process runtime functions
  5.  
  6.     Owned by: Tantek Çelik
  7.  
  8.     Copyright:    © 1994 - 1995 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.         <52>    10/31/95    TJ        Made the Splash Screen Non-Modal.#1297413
  13.         <51>    10/26/95    TÇ        1296574 GM:Cannot set default memory
  14.                                     partition size.
  15.         <50>    10/25/95    TÇ        1281409 GM: OpenDoc needs an AboutBox.
  16.         <49>    10/12/95    eeh        1287143: check for open resource forks
  17.         <48>     9/29/95    eeh        1287262: use ShellDef.h
  18.         <47>     9/27/95    TÇ        1287770 GM:Crash when an application is
  19.                                     dragged over the launcher
  20.         <46>     9/27/95    eeh        1284464: use ClipStringToBytes
  21.         <45>      9/8/95    eeh        1268998: get prefs file name from resource
  22.         <44>      9/8/95    CG        #1282518 FB1:Shell moves "bad" aliases from
  23.                                     OD Libs fldr if found.
  24.         <43>      9/8/95    TÇ        1271995 FB1:Get error -35 or -44 opening
  25.                                     stationery off write-protected volume
  26.         <42>      9/5/95    TÇ        1281030 FB1:OpenDoc(tm) corrupts ODF Shared
  27.                                     libraries
  28.         <41>     8/29/95    jpa        Rename Toolbox calls for Univ Hdrs 2.1.
  29.                                     [1279173]
  30.         <40>     8/26/95    TÇ        1269688 FB1:  There is an unnecessary
  31.                                     variable
  32.         <39>     8/22/95    eeh        1278280: include RlShlDef.h
  33.         <38>     8/22/95    eeh        1276821:
  34.                                     kOpenDocShellSignature->kODShellSignature
  35.         <37>     8/16/95    CG        #1274825: Fixed creating stationery for
  36.                                     libs containing multiple editors.
  37.         <36>      8/3/95    TÇ        Remove dependency on obsolete SysPrDef.h
  38.         <35>     6/30/95    TÇ        1251872 BB: Can't open stationery if file
  39.                                     name becomes too long. 1264094 BB:Custom
  40.                                     document size cannot be attached to a
  41.                                     stationery.
  42.         <34>     6/25/95    TÇ        1242642 BB: Turn on ODDebug warning if
  43.                                     refcount is wrong in
  44.                                     ODRefCntObjectsomUninit.
  45.         <33>      6/2/95    TÇ        Need to copy resources into newly created
  46.                                     documents.  Completes fix to 4
  47.                                     BB:1233106,1242232, 1254312, 1242283
  48.         <32>     5/25/95    jpa        Removed CODE 7 -- CFM68K b1 doesn't
  49.                                     generate one. [1241078]
  50.         <31>     5/19/95    TÇ        1155852 BB: String constants need to be
  51.                                     moved to resource for Localization, 1235942
  52.                                     Launching the OpenDoc pref file causes a
  53.                                     1000 exception to be thrown, 1249396 (was
  54.                                     BB) OpenDoc shell should serialize
  55.                                     stationery creation.
  56.         <30>     5/10/95    CG        #1243610    BB: Shell should not rely on the
  57.                                     constant kNMAPid.
  58.         <29>      5/7/95    TÇ        1155852 BB: String constants need to be
  59.                                     moved to resource for Localization (mostly
  60.                                     done)
  61.         <28>     4/29/95    TÇ        1216130 BB: Shell should open top draft
  62.                                     upon receipt of open document Apple event
  63.         <27>     4/24/95    eeh        1216915: remove unnecessary param
  64.         <26>     4/24/95    eeh        1240662: send keyODActivateEventCause param
  65.                                     in activate event
  66.         <25>     4/15/95    TÇ        #1216915 DR/BB:Trying to open a document
  67.                                     that is already open causes an error.
  68.         <24>     4/14/95    TÇ        #1186294    DR/BB: Binding for editor also
  69.                                     affect making stationary.
  70.         <23>      4/7/95    eeh        1221297: eventID param to
  71.                                     VerifyAndLaunchDocumentStub
  72.         <22>     3/31/95    TÇ        1223465 BB: Opening and creating documents
  73.                                     under low disk space.  (Creating documents
  74.                                     under low disk space part fixed).
  75.                                     1211032 BB: Invalid Permissions error
  76.                                     opening locked document
  77.         <21>     3/28/95    TÇ        #1151710 BB: Toolbox running out of app
  78.                                     heap.  Document Size dialog implemented.
  79.                                     TestAndVerify now uses SIZE -1 resource in
  80.                                     OpenDoc Preferences if it exists.
  81.         <20>     3/24/95    CG        #1226064: ODTestmain can create stationary.
  82.         <19>     2/24/95    EL        1220392: fix access check bug in last
  83.                                     checkin.
  84.         <18>     2/23/95    EL        1220392: checking read only fails on file
  85.                                     share volumes.
  86.         <17>     2/20/95    TÇ        #1210979 BB: 5-$ Bugs need to be evaluated
  87.                                     and removed from Shell
  88.                                     #1221861 BB: Incomplete AOCE support needs
  89.                                     to be removed from OpenDoc
  90.         <16>     2/13/95    TÇ        1193359: BB: Opening stationery on other
  91.                                     volume causes bus error in Messaging code
  92.                                     1211032: BB: Invalid Permissions Error
  93.                                     opening locked document
  94.         <15>      2/2/95    CG        #1205177:  "Editors" and "OpenDoc
  95.                                     Libraries" folders are being registered
  96.                                     with cfm (PPC only).
  97.         <14>     1/12/95    jpa        Removed HandToHand workaround for bug in
  98.                                     Dagon a1 [1210936]
  99.         <13>      1/6/95    jpa        Added new docstub rsrcs to tables [1196515]
  100.         <12>     12/5/94    jpa        Added GetLaunchFailedParams. [1198075,
  101.                                     1158966]
  102.         <11>    10/24/94    jpa        Took out WASSERTM call & Use BlockMove, not
  103.                                     BlockMoveData [68k].
  104.         <10>    10/12/94    TÇ        68K: use local static version of HandToHand
  105.          <9>    10/10/94    TÇ        #1191470 Need both 68K and PPC document
  106.                                     stub application
  107.          <8>     10/7/94    TÇ        #1191470 Need both 68K and PPC document
  108.                                     stub application
  109.          <7>     9/29/94    RA        1189812: Mods for 68K build.
  110.          <6>      9/8/94    eeh        #1185443: forgot to eliminate strcat and
  111.                                     strcpy.
  112.          <5>      9/8/94    eeh        #1185443.  Lotso changes to separate
  113.                                     document with content from what gets
  114.                                     launched.
  115.          <4>     8/29/94    TÇ        #1158280 OpenDoc™ should not overwrite old
  116.                                     stationery files when creating new ones
  117.          <3>     8/25/94    TÇ        #1183223 Enabled launching of documents in
  118.                                     folders other than that of the OpenDoc
  119.                                     libraries.  Added new call:
  120.                                     VerifyAndLaunchDocument
  121.          <2>     8/22/94    TÇ        #1182448 System Process quits when no
  122.                                     OpenDoc documents are running
  123.          <1>     8/22/94    TÇ        first checked in
  124.          
  125.     To Do:
  126.         Change all uses of ODFileSpec and FSSpecPtr to PlatformFile objects
  127.     In Progress:
  128.         
  129. */
  130.  
  131. #ifndef _EXCEPT_
  132. #include <Except.h>
  133. #endif
  134.  
  135. #ifndef _ODDEBUG_
  136. #include "ODDebug.h"
  137. #endif
  138.  
  139. #ifndef _ODPRCS_
  140. #include "ODPrcs.h"
  141. #endif
  142.  
  143. #ifndef _SHELLDEF_
  144. #include "ShellDef.h"
  145. #endif
  146.  
  147. #ifndef SOM_Module_OpenDoc_StdDefs_defined
  148. #include <StdDefs.xh>
  149. #endif
  150.  
  151. #ifndef SOM_Module_OpenDoc_ODRegistry_defined
  152. #include "ODRgstry.xh"
  153. #endif
  154.  
  155. #ifndef _PLFMFILE_
  156. #include "PlfmFile.h"
  157. #endif
  158.  
  159. #ifndef _PASCLSTR_
  160. #include "PasclStr.h"
  161. #endif
  162.  
  163. #ifndef __ERRORS__
  164. #include <Errors.h>
  165. #endif
  166.  
  167. #ifndef __FOLDERS__
  168. #include <Folders.h>
  169. #endif
  170.  
  171. #ifndef __OSEVENTS__
  172. #include <OSEvents.h>
  173. #endif
  174.  
  175. #ifndef __ALIASES__
  176. #include <Aliases.h>
  177. #endif
  178.  
  179. #ifndef __FILES__
  180. #include <Files.h>
  181. #endif
  182.  
  183. #ifndef __RESOURCES__
  184. #include <Resources.h>
  185. #endif
  186.  
  187. #ifndef __DIALOGS__
  188. #include <Dialogs.h>
  189. #endif
  190.  
  191. #ifndef __EVENTS__
  192. #include <Events.h>
  193. #endif
  194.  
  195. #ifndef __APPLEEVENTS__
  196. #include <AppleEvents.h>
  197. #endif
  198.  
  199. #ifndef __PROCESSES__
  200. #include <Processes.h>
  201. #endif
  202.  
  203. #ifndef __STRING__
  204. #include <String.h>
  205. #endif
  206.  
  207. #ifndef __TEXTUTILS__
  208. #include <TextUtils.h>
  209. #endif
  210.  
  211. #ifndef __SCRIPT__
  212. #include <script.h>
  213. #endif
  214.  
  215. #ifndef __FINDER__
  216. #include <Finder.h>
  217. #endif
  218.  
  219. #ifndef _ODMEMORY_
  220. #include <ODMemory.h>
  221. #endif
  222.  
  223. #ifndef _REGISTER_
  224. #include <RegisterFileLibs.h>
  225. #endif
  226.  
  227. //==============================================================================
  228. // Constants
  229. //==============================================================================
  230.  
  231. #define kMaxFileNameLen        31
  232.  
  233. #define kNumDocStubRsrcs    11    /* was 12 before CFM68K a3 */
  234.  
  235. const ODULong docStubRsrcType[kNumDocStubRsrcs] = 
  236.     {     kDocStubRsrcType,
  237.         kDocStubRsrcType,
  238.         kDocStubRsrcType,
  239.         kDocStubRsrcType,
  240.         kDocStubRsrcType,
  241.         kDocStubRsrcType,
  242.         kDocStubRsrcType,
  243.         kDocStubRsrcType,
  244. //        kDocStubRsrcType,
  245.         kDocStubRsrcType,
  246.         kDocStubRsrcType,
  247.         kSIZERsrcType 
  248.     };
  249.  
  250. const ODULong docStubRsrcID[kNumDocStubRsrcs] = 
  251.     {    kDocStubRsrcID0,
  252.         kDocStubRsrcID1,
  253.         kDocStubRsrcID2,
  254.         kDocStubRsrcID3,
  255.         kDocStubRsrcID4,
  256.         kDocStubRsrcID5,
  257.         kDocStubRsrcID6,
  258.         kDocStubRsrcID7,
  259.         kDocStubRsrcID8,
  260.         kDocStubRsrcID9,
  261. //        kDocStubRsrcID10,
  262.         kDocStubSIZEID
  263.     };
  264.  
  265. const ODULong copiedRsrcType[kNumDocStubRsrcs] = 
  266.     {     kcfrgRsrcType,
  267.         kMainCFMType,
  268.         kscszRsrcType,
  269.         kMainCFMType,
  270.         kMainCFMType,
  271.         kCODERsrcType,
  272.         kCODERsrcType,
  273.         kCODERsrcType,
  274. //        kCODERsrcType,
  275.         kMainCFMType,
  276.         kMainCFMType,
  277.         kSIZERsrcType 
  278.     };
  279.  
  280. const ODULong copiedRsrcID[kNumDocStubRsrcs] = 
  281.     {    kcfrgID,
  282.         kMainCFMPPCID,
  283.         kscszID,
  284.         kMainCFM68KID,
  285.         kMainCFM68KID1,
  286.         kCODEID0,
  287.         kCODEID1,
  288.         kCODEID6,
  289. //        kCODEID7,
  290.         kSOMMemCFM68KID,
  291.         kSOMMemCFMPPCID,
  292.         kSIZEID
  293.     };
  294.  
  295.  
  296. enum
  297. {
  298.     kIsNotSameAsStub        = 0,
  299.     kIsSameAsStub            = 1,
  300.     kIsAlreadyLaunched        = 2
  301. };
  302. typedef ODSShort DocStubType;
  303.  
  304. struct ITextData {
  305.     ScriptCode      theScriptCode;
  306.     LangCode     theLangCode;
  307.     Str255         theText;
  308. };
  309. typedef struct ITextData ITextData;
  310.  
  311. struct EditorUserStringList {
  312.     Str255                     editor;
  313.     ITextData                name;
  314.     EditorUserStringList*     next;
  315. };
  316. typedef struct EditorUserStringList EditorUserStringList;
  317.  
  318. //==============================================================================
  319. // Macros
  320. //==============================================================================
  321.  
  322. #define CHECK(EXPR)    if ((err=(EXPR)) == noErr) ; else return err
  323. #define CHECKR(EXPR,RET)    if ((err=(EXPR)) == noErr) ; else return (RET)
  324.  
  325. //==============================================================================
  326. // Function Prototype
  327. //==============================================================================
  328.  
  329. static ODBoolean    IsAProcessRunning(OSType procType, OSType procSignature);
  330.  
  331. static void    CreateTempName(short seed, Str255 name, ODBoolean isFile);
  332. static OSErr CreateUniqueTmpFolderForFile(ODFileSpec* result,
  333.         Str63 fileName);
  334. static OSErr MakeDocumentStub(AEDesc *document, FSSpec* documentStub,
  335.         FSSpec* documentSpec,
  336.         DocStubType* isDuplicate, DescType eventID);
  337.  
  338. // Document Launching
  339. static OSErr     TestAndUpdate(Handle origRsrc,ResType rtype,short rid);
  340. static OSErr    CreateStationerySeed(FSSpecPtr theDocument, FSSpec* seedFSSPtr);
  341. static size_t    ODXstrlen(const char *s);
  342. static char*     ODXstrncpy(char* destStr, char* srcStr, size_t n);
  343. static char*     ODXstrncat(char* destStr, char* srcStr, size_t n);
  344. static char        ODXmemcmp(char* buffer1,char* buffer2,unsigned int len);
  345. ODBoolean myEqualPascalStrings(ConstStr255Param str1, ConstStr255Param str2);
  346. static ODSLong GetFldrDirID(ODFileSpec theFolderSpec);
  347. ODFileSpec    FindODBinary(ODSShort fldrVRefNum, 
  348.                                         ODSLong fldrDirID, Str255 pbinaryName);
  349. OSErr GetEditorUserStringPairs(ODSShort resRefNum, EditorUserStringList** pairs, ODUShort* editorCount);
  350. OSErr GetEditorSetFromNMAP( ODHandle nmap, EditorUserStringList** pairs, ODUShort* editorCount );
  351. static void MoveToTrash( short vRefnum, long dirID, Str255 name );
  352.  
  353.  
  354. //==============================================================================
  355. // GetOpenDocBinaryFileSpec
  356. //==============================================================================
  357.  
  358. ODFileSpec    GetOpenDocBinaryFileSpec(char* binaryName)
  359. {
  360.  
  361.     ODFileSpec filespec;
  362.     Str255    pbinaryName;
  363.     ODUShort pbinaryLen = 0;
  364.     
  365.     if (binaryName)
  366.     {
  367.         pbinaryLen = ODXstrlen(binaryName);
  368.         
  369.         if (pbinaryLen>255)
  370.         {
  371.             pbinaryLen = 255;
  372.         }
  373.         
  374.         ODXstrncpy((char*)&(pbinaryName[1]),binaryName,pbinaryLen);
  375.     }
  376.     
  377.     ClipStringToBytes( pbinaryName, pbinaryLen, smCurrentScript );
  378.     
  379.     ODFileSpec odLibsFldrSpec = GetOpenDocLibsFldrSpec();
  380.     ODSLong dirID = GetFldrDirID(odLibsFldrSpec);
  381.     filespec = FindODBinary(odLibsFldrSpec.vRefNum, dirID, pbinaryName);
  382.  
  383.     return filespec;
  384. }
  385.  
  386. //==============================================================================
  387. // FindODBinary
  388. //==============================================================================
  389.  
  390. ODFileSpec    FindODBinary(ODSShort fldrVRefNum, 
  391.                                          ODSLong fldrDirID, Str255 pbinaryName)
  392. {
  393.     CInfoPBRec        CinfoPB;
  394.     Str255            fileName;
  395.     ODFileSpec        fileSpec;
  396.     FSMakeFSSpec(    fldrVRefNum, 
  397.                      fldrDirID, 
  398.                      pbinaryName, &fileSpec);
  399.  
  400.         //check that this is not a bogus folder
  401.     if (fldrDirID != -1)
  402.     {
  403.         memset (&CinfoPB,0,sizeof(CinfoPB));
  404.         CinfoPB.dirInfo.ioNamePtr = (StringPtr)&fileName;
  405.         CinfoPB.dirInfo.ioFDirIndex = 1;
  406.         CinfoPB.dirInfo.ioVRefNum = fldrVRefNum;
  407.         CinfoPB.dirInfo.ioDrDirID = fldrDirID;
  408.         
  409.             // Loop through all the files in Library folder
  410.         for(ODSShort i = PBGetCatInfoSync(&CinfoPB); 
  411.                         i == noErr; 
  412.                        i = PBGetCatInfoSync(&CinfoPB))
  413.         {
  414.                 // if this is a folder
  415.             if ((CinfoPB.dirInfo.ioFlAttrib & (1<<4))) 
  416.             {
  417.                 FSSpec fldrSpec;
  418.                 FSMakeFSSpec(CinfoPB.hFileInfo.ioVRefNum, 
  419.                              CinfoPB.hFileInfo.ioFlParID, 
  420.                              fileName, &fldrSpec);
  421.                 OSErr err = RegisterFileLibs(&fldrSpec);
  422.                 fileSpec = FindODBinary(fldrVRefNum, 
  423.                                         CinfoPB.dirInfo.ioDrDirID, 
  424.                                         pbinaryName);
  425.             }
  426.             else
  427.             {
  428.                     // if this is an alias, resolve and do the right thing
  429.                 if ((CinfoPB.hFileInfo.ioFlFndrInfo.fdFlags & 0x8000) /* kIsAlias */)
  430.                 {
  431.                     FSSpec    aliasSpec;
  432.                     Boolean    targetIsFolder = kODFalse;
  433.                     Boolean    wasAliased = kODFalse;
  434.                     
  435.                     ODError result = FSMakeFSSpec(CinfoPB.hFileInfo.ioVRefNum, 
  436.                                           CinfoPB.hFileInfo.ioFlParID, 
  437.                                           fileName, &aliasSpec);
  438.                     if (result == noErr)
  439.                     {
  440.                             //resolve alias
  441.                         result = ResolveAliasFile(&aliasSpec, kODTrue, 
  442.                                               &targetIsFolder, &wasAliased);
  443.                         if (result == noErr)
  444.                         {
  445.                             if (aliasSpec.vRefNum != fldrVRefNum)
  446.                                 MoveToTrash( CinfoPB.hFileInfo.ioVRefNum, 
  447.                                              CinfoPB.hFileInfo.ioFlParID, fileName );
  448.                             else
  449.                             {
  450.                                 if (targetIsFolder)
  451.                                 {
  452.                                     OSErr err = RegisterFileLibs(&aliasSpec);
  453.                                     ODSLong dirID = GetFldrDirID(aliasSpec);
  454.                                     FindODBinary(aliasSpec.vRefNum, 
  455.                                                   dirID, pbinaryName);
  456.                                 }
  457.                                 else
  458.                                 {
  459.                                     // if this file's name == pbinaryName, make an FSSpec and return it
  460.                                     if (myEqualPascalStrings(pbinaryName, 
  461.                                                               fileName))
  462.                                         FSMakeFSSpec(aliasSpec.vRefNum, 
  463.                                                       aliasSpec.parID, fileName, 
  464.                                                       &fileSpec);                                    
  465.                                 }
  466.                             }
  467.                         }
  468.                     }
  469.                 }
  470.                 else
  471.                 {
  472.                     // if this file's name == pbinaryName, make an FSSpec and return it
  473.                     if (myEqualPascalStrings(pbinaryName, fileName))
  474.                     {
  475.                         FSMakeFSSpec(CinfoPB.hFileInfo.ioVRefNum, 
  476.                                       CinfoPB.hFileInfo.ioFlParID, 
  477.                                       fileName, &fileSpec);
  478.                     }                            
  479.                 }
  480.             }
  481.  
  482.             CinfoPB.hFileInfo.ioFDirIndex++;
  483.                 //need to do this each time since PBGetCatInfo call returns val here
  484.             CinfoPB.hFileInfo.ioNamePtr = (StringPtr)&fileName;
  485.             CinfoPB.hFileInfo.ioVRefNum = fldrVRefNum;
  486.             CinfoPB.hFileInfo.ioDirID = fldrDirID;  
  487.         }
  488.     }
  489.     return fileSpec;
  490. }
  491.  
  492. //==============================================================================
  493. // GetOpenDocLibsFldrSpec
  494. //==============================================================================
  495.  
  496. ODFileSpec    GetOpenDocLibsFldrSpec()
  497. {
  498.     ODSLong        odDirID, libsFldrDirID;
  499.     ODSShort    odVRef, libsFldrVRefNum;
  500.     ODFileSpec    odFldrSpec;
  501.     Str255        folderName;
  502.  
  503.     GetIndString(folderName, kODXLibsFldrStrID, kODXLibsFldrStrIndex);
  504. #if ODDebug
  505.     if (folderName[0] == 0)
  506.         DebugStr("\pResource Error: OpenDoc Libraries string not found!");
  507. #endif
  508.         
  509.     ODError result = FindFolder(kOnSystemDisk, kExtensionFolderType, 
  510.                                 kDontCreateFolder, &libsFldrVRefNum, 
  511.                                 &libsFldrDirID);
  512.     if (result == noErr)
  513.     {
  514.         CInfoPBRec        CinfoPB;
  515.         memset (&CinfoPB,0,sizeof(CinfoPB));
  516.         CinfoPB.dirInfo.ioNamePtr = (StringPtr)&folderName;
  517.         CinfoPB.dirInfo.ioFDirIndex = 0;
  518.         CinfoPB.dirInfo.ioVRefNum = libsFldrVRefNum;
  519.         CinfoPB.dirInfo.ioDrDirID = libsFldrDirID;
  520.         
  521.         ODSShort result = PBGetCatInfoSync(&CinfoPB);
  522.         if (result == noErr)
  523.         {
  524.             odVRef  = CinfoPB.dirInfo.ioVRefNum;
  525.             odDirID = CinfoPB.dirInfo.ioDrParID;
  526.             result = FSMakeFSSpec(odVRef, odDirID, folderName, &odFldrSpec);
  527.         }
  528.     }
  529.     
  530.     return odFldrSpec;
  531. }
  532.  
  533. //------------------------------------------------------------------------------
  534. // GetFldrDirID
  535. //------------------------------------------------------------------------------
  536. static ODSLong
  537. GetFldrDirID(ODFileSpec theFolderSpec)
  538. {
  539.     ODSLong dirID=-1;
  540.     CInfoPBRec    theParamBlock;
  541.     memset (&theParamBlock,0,sizeof(theParamBlock));
  542.     theParamBlock.dirInfo.ioFDirIndex = 0;
  543.     theParamBlock.dirInfo.ioNamePtr = theFolderSpec.name;
  544.     theParamBlock.dirInfo.ioVRefNum = (ODSShort)theFolderSpec.vRefNum;
  545.     theParamBlock.dirInfo.ioDrDirID = (ODSLong)theFolderSpec.parID;
  546.     ODError result = PBGetCatInfoSync((CInfoPBPtr)&theParamBlock);
  547.     if (result == noErr && (theParamBlock.hFileInfo.ioFlAttrib & (1<<4))) 
  548.         dirID = theParamBlock.dirInfo.ioDrDirID;
  549.  
  550.     return dirID;
  551. }
  552.  
  553. #ifdef NEEDSYSTEMPROCESS
  554. #define    kODSysProcessType            0x4150504C    // 'APPL' ?should be 'appe' eventually
  555. #define kODSysProcessSignature        0x6F647370    // 'odsp'
  556.  
  557. //==============================================================================
  558. // IsODSysProcessRunning
  559. //==============================================================================
  560.  
  561. ODBoolean    IsODSysProcessRunning()
  562. {
  563.     return IsAProcessRunning(kODSysProcessType,kODSysProcessSignature);
  564.  
  565.     ProcessSerialNumber psn = {0,kNoProcess};
  566.     ProcessInfoRec aProcess;
  567.     aProcess.processInfoLength = sizeof(ProcessInfoRec);
  568.     aProcess.processName = NULL;
  569.     aProcess.processAppSpec = NULL;
  570.     
  571.     while (GetNextProcess(&psn) == noErr)
  572.         if (GetProcessInformation(&psn,&aProcess) == noErr)
  573.             if (aProcess.processType == kODSysProcessType &&
  574.                 aProcess.processSignature == kODSysProcessSignature)
  575.                     return true;
  576.     return false;
  577. }
  578. #endif
  579.  
  580. //==============================================================================
  581. // AreODDocumentsRunning
  582. //==============================================================================
  583.  
  584. ODBoolean    AreODDocumentsRunning()
  585. {
  586.     ProcessSerialNumber psn = {0,kNoProcess};
  587.     ProcessInfoRec aProcess;
  588.     aProcess.processInfoLength = sizeof(ProcessInfoRec);
  589.     aProcess.processName = NULL;
  590.     aProcess.processAppSpec = NULL;
  591.     
  592.     while (GetNextProcess(&psn) == noErr)
  593.         if (GetProcessInformation(&psn,&aProcess) == noErr)
  594.             if (aProcess.processType != 'APPL' &&
  595.                 aProcess.processSignature == kODShellSignature)
  596.                     return true;
  597.     return false;
  598. }
  599.  
  600. //==============================================================================
  601. // FileIsReadOnly
  602. //==============================================================================
  603.  
  604. OSErr FileIsReadOnly(ODFileSpec* fs, ODBoolean* result)
  605. {
  606. // Note: copied from PlatformFile::IsLocked.  OpenDoc™ DOES NOT link in Util.lib. -TÇ
  607.  
  608.     CInfoPBRec    pbBlock;
  609.     *result = kODFalse;
  610.     OSErr err = noErr;
  611.  
  612.     // Check to see whether the volume is locked
  613.  
  614.     // Eric's original code with slight modifications.
  615.     // Appears to be needed in the case of a locked floppy. -TÇ
  616.     HParamBlockRec pb;
  617.     pb.volumeParam.ioCompletion = kODNULL;
  618.     pb.volumeParam.ioNamePtr = kODNULL;
  619.     pb.volumeParam.ioVRefNum = fs->vRefNum;
  620.     pb.volumeParam.ioVolIndex = 0;
  621.  
  622.     err = PBHGetVInfoSync(&pb);
  623.     if (err) return err;
  624.  
  625.     // <eeh> I have no clue if this 0x80 is right!!!  Find out what
  626.     // the constant is for write-access possible....
  627.  
  628.     *result = (pb.volumeParam.ioVAtrb & 0x80) ? kODTrue : kODFalse;
  629.     
  630.     // Check to see whether the directory is locked
  631.     if (*result == kODFalse) {
  632.         // first assume it is a file share volume
  633.         HParamBlockRec    paramBlk;
  634.         paramBlk.accessParam.ioCompletion = kODNULL;
  635.         paramBlk.accessParam.ioNamePtr = kODNULL;
  636.         paramBlk.accessParam.ioVRefNum = fs->vRefNum;
  637.         paramBlk.accessParam.ioDirID = fs->parID;
  638.         paramBlk.accessParam.ioACAccess = 0;
  639.         err = PBHGetDirAccessSync(¶mBlk);
  640.         
  641.         if (err == noErr) {        /* it is a file share volume, look at the access right */
  642.             if ((paramBlk.accessParam.ioACAccess & 0x04000000) == 0) /* no write access */
  643.                 *result = kODTrue;
  644.         }
  645.         else if (err == paramErr) { /* it is not file share, look at directory */
  646.             pbBlock.dirInfo.ioCompletion = kODNULL;
  647.             pbBlock.dirInfo.ioNamePtr = kODNULL;
  648.             pbBlock.dirInfo.ioVRefNum = fs->vRefNum;
  649.             pbBlock.dirInfo.ioFDirIndex = -1;
  650.             pbBlock.dirInfo.ioDrDirID = fs->parID;
  651.             pbBlock.dirInfo.ioFlAttrib = 0;
  652.             err = PBGetCatInfoSync(&pbBlock);
  653.             if (err) return err;
  654.             if (pbBlock.dirInfo.ioFlAttrib & 1)
  655.                 *result = kODTrue;            
  656.         }
  657.         else
  658.             return err;
  659.     }
  660.  
  661.     // Check to see whether the file is locked
  662.     if (*result == kODFalse) {    
  663.         pbBlock.hFileInfo.ioCompletion = kODNULL;
  664.         pbBlock.hFileInfo.ioFDirIndex = 0;
  665.         pbBlock.hFileInfo.ioNamePtr = fs->name;
  666.         pbBlock.hFileInfo.ioVRefNum = fs->vRefNum;
  667.         pbBlock.hFileInfo.ioDirID = fs->parID;
  668.         
  669.         err =  PBGetCatInfoSync(&pbBlock);
  670.         if (err) return err;
  671.  
  672.         if (pbBlock.hFileInfo.ioFlAttrib & 1)
  673.             *result = kODTrue;
  674.     }
  675.             
  676.     return noErr;
  677. }
  678.  
  679. //==============================================================================
  680. // GetVolumeWritableSpace
  681. //==============================================================================
  682.  
  683. ODULong    GetVolumeWritableSpace(ODFileSpec* fs, ODULong* error)
  684. {    
  685.     ODULong err = noErr;
  686.     HParamBlockRec    paramBlk;
  687.     ODBoolean        writable = kODFalse;
  688.     
  689.     if (error == kODNULL)
  690.         error = &err;
  691.         
  692.     paramBlk.accessParam.ioCompletion = kODNULL;
  693.     paramBlk.accessParam.ioNamePtr = kODNULL;
  694.     paramBlk.accessParam.ioVRefNum = fs->vRefNum;
  695.     paramBlk.accessParam.ioDirID = fs->parID;
  696.     paramBlk.accessParam.ioACAccess = 0;
  697.     *error = PBHGetDirAccessSync(¶mBlk);
  698.     
  699.     if (*error == noErr) {        /* it is a file share volume, look at the access right */
  700.         if (paramBlk.accessParam.ioACAccess & 0x04000000)
  701.             writable = kODTrue;
  702.     }
  703.     else if (*error == paramErr) { /* it is not file share, look at directory */
  704.         CInfoPBRec    pbBlock;
  705.         pbBlock.dirInfo.ioCompletion = kODNULL;
  706.         pbBlock.dirInfo.ioNamePtr = kODNULL;
  707.         pbBlock.dirInfo.ioVRefNum = fs->vRefNum;
  708.         pbBlock.dirInfo.ioFDirIndex = -1;
  709.         pbBlock.dirInfo.ioDrDirID = fs->parID;
  710.         pbBlock.dirInfo.ioFlAttrib = 0;
  711.         *error = PBGetCatInfoSync(&pbBlock);
  712.         if (*error) return 0;
  713.         
  714.         if (!(pbBlock.dirInfo.ioFlAttrib & 1))
  715.             writable = kODTrue;
  716.     }
  717.     else
  718.          return 0;
  719.  
  720.     if (writable != kODFalse) {
  721.         // how much space on this writable volume?
  722.         HParamBlockRec hpb;
  723.         hpb.volumeParam.ioVolIndex = 0;
  724.         hpb.volumeParam.ioNamePtr = kODNULL;
  725.         hpb.volumeParam.ioVRefNum = fs->vRefNum;
  726.         
  727.         *error = PBHGetVInfoSync(&hpb);
  728.         if (*error) return 0;
  729.         
  730.         if (!(hpb.volumeParam.ioVAtrb & 0x80))
  731.             return ((hpb.volumeParam.ioVFrBlk * hpb.volumeParam.ioVAlBlkSiz) / 1024);
  732.         // Appears to be needed in the case of a locked floppy. -TÇ
  733.         // <eeh> I have no clue if this "0x80" is right!!!  Find out what
  734.         // the constant is for write-access possible....
  735.     }    
  736.  
  737.     *error = kODErrDirectoryNotHaveWriteAccess;
  738.     return 0;
  739. }
  740.  
  741. //==============================================================================
  742. // GetDescFSSpec
  743. //==============================================================================
  744.  
  745. OSErr
  746. GetDescFSSpec(AEDesc *desc, FSSpec &spec)
  747. {
  748.     AEDesc resultDesc;
  749.     OSErr err = AECoerceDesc(desc, typeFSS, &resultDesc);
  750.     if (err) return err;
  751.     spec = **(FSSpec**)(resultDesc.dataHandle);
  752.     AEDisposeDesc(&resultDesc);
  753.     return noErr;
  754. }
  755.  
  756.  
  757. //==============================================================================
  758. // MakeDocumentStub
  759. //==============================================================================
  760.  
  761. static void    CreateTempName(short seed, Str255 name, ODBoolean isFile)
  762. {
  763.     // Don't modify this one!
  764.     char* nmSeed = isFile? "ODShellTempFile" : "ODShellTempFolder";
  765.     ODXstrncpy((char*)name, nmSeed, ODXstrlen(nmSeed)+1);
  766.  
  767.     char theNum[10];
  768.     NumToString(seed, (StringPtr)theNum); 
  769. //    WASSERT(theNum[0] <= 5);
  770.     p2cstr((StringPtr)theNum);
  771.  
  772.     ODXstrncat((char*)name, theNum, ODXstrlen(theNum)+1);
  773.     c2pstr((char *)name);
  774. }
  775.  
  776. OSErr CreateUniqueTmpFolderForFile(ODFileSpec* result,
  777.         Str63 fileName)
  778. {
  779.     Str255        myName;
  780.     ODSLong    myDirID;
  781.     ODSShort    myVRef;
  782.  
  783.     FindFolder(kOnSystemDisk, kTemporaryFolderType, kCreateFolder, &myVRef, &myDirID);
  784.  
  785.     OSErr err;
  786.     short limit = 100;
  787.     short seed = 1;
  788.     while (--limit)
  789.     {
  790.         CreateTempName(seed++, myName, kODFalse);
  791.         long createdDirID;
  792.         err = DirCreate(myVRef, myDirID, myName,
  793.                 &createdDirID);
  794.         if (err == noErr)
  795.         {
  796.             FSMakeFSSpec(myVRef, createdDirID, fileName, result);
  797.             return noErr;
  798.         }
  799.     }
  800.     return err;
  801. }
  802.  
  803. static OSErr MakeDocumentStub(AEDesc *document, FSSpec* documentStub,
  804.                                 FSSpec* documentSpec,
  805.                                 DocStubType* isDuplicate,
  806.                                 DescType eventID)
  807. {
  808.     OSErr err;
  809.     
  810.     FSSpec documentFSSpec;
  811.     CHECK(GetDescFSSpec(document, documentFSSpec));
  812.     *documentSpec = documentFSSpec;
  813.  
  814.     if (WasLaunchedThenActivate(documentSpec, eventID, err ))
  815.     {
  816.         *isDuplicate = kIsAlreadyLaunched;
  817.         return err;
  818.     }
  819.  
  820.     FInfo documentFInfo;
  821.     err= FSpGetFInfo(&documentFSSpec, &documentFInfo);
  822.     if (err) return err;
  823.  
  824.     // if it's a read-only file OR if it's on a server OR if it's stationery,
  825.     // make a new one.
  826.     
  827.     ODBoolean makeNewOne;
  828.     err = FileIsReadOnly(&documentFSSpec, &makeNewOne);
  829.     if (err) return err;
  830.     makeNewOne = makeNewOne || (((documentFInfo.fdFlags)&kIsStationary)!=0) ||
  831.         (documentFInfo.fdCreator != kODShellSignature);
  832.     if (!makeNewOne || 
  833.         documentFInfo.fdType == kEditorFileType)
  834.     {
  835.         *documentStub = documentFSSpec;
  836.         *isDuplicate = kIsSameAsStub;
  837.         return noErr;
  838.     }
  839.     
  840.     // if we get here we need a new file....
  841.     *isDuplicate = kIsNotSameAsStub;
  842.  
  843.     FSSpec newFileSpec;
  844.     err = CreateUniqueTmpFolderForFile(&newFileSpec, documentFSSpec.name);    
  845.     if (err) return err;
  846.  
  847.     err = FSpCreate(&newFileSpec, kODShellSignature, documentFInfo.fdType, 0);
  848.     FSpCreateResFile(&newFileSpec, kODShellSignature, documentFInfo.fdType, 0);
  849.     if (!err)
  850.         *documentStub = newFileSpec;
  851.  
  852.     // Need to copy over custom SIZE 0 & 1 resource for proper custom heapsize behaviour
  853.     // for readonly documents and documents newly created from stationery.
  854.     
  855.     short theCurResFile = CurResFile();
  856.     short docResFile = FSpOpenResFile((const FSSpec *)&documentFSSpec,fsRdPerm);
  857.     
  858.     if (docResFile != -1)
  859.     {
  860.         ODHandle size0 = kODNULL;
  861.         size0 = Get1Resource(kSIZERsrcType, 0);
  862.         if (size0)
  863.             DetachResource(size0);
  864.         ODHandle size1 = kODNULL;
  865.         size1 = Get1Resource(kSIZERsrcType, 1);
  866.         if (size1)
  867.             DetachResource(size1);
  868.         CloseResFile( docResFile );
  869.         
  870.         short stubResFile = FSpOpenResFile((const FSSpec *)&newFileSpec,fsRdWrPerm);
  871.         if (size0)
  872.             err = TestAndUpdate(size0,kSIZERsrcType,0);
  873.         if (!err && size1)
  874.             err = TestAndUpdate(size1,kSIZERsrcType,1);
  875.         CloseResFile( stubResFile );
  876.         
  877.         if (size0)
  878.             DisposeHandle(size0);
  879.         if (size1)
  880.             DisposeHandle(size1);
  881.  
  882.         UseResFile(theCurResFile);
  883.     }
  884.  
  885.     return err;
  886. }
  887.  
  888. //==============================================================================
  889. // WasLaunchedThenActivate
  890. //==============================================================================
  891.  
  892.  
  893. ODBoolean    WasLaunchedThenActivate(
  894.                         FSSpec* fileSpec,
  895.                         DescType eventID,
  896.                         OSErr & err)
  897. {
  898.     // check if the file we want to open is already open by someone on this machine
  899.     ODULong        refNumCount = 0;
  900.     RefNumPtr    refNums = kODNULL;
  901.  
  902.     CHECKR(GetLocalPaths(fileSpec, kDataFork, &refNumCount, &refNums), kODFalse);
  903.     DisposePtr((Ptr) refNums);
  904.     refNums = kODNULL;
  905.     ODBoolean refnumForResFork = refNumCount == 0;    // don't count on
  906.                                                     // refnumForResFork in the
  907.                                                     // case where
  908.                                                     // we're returning false
  909.     if ( refnumForResFork )        // try again with the resource fork
  910.     {
  911.         CHECKR(GetLocalPaths(fileSpec, kResourceFork, &refNumCount, &refNums),
  912.                 kODFalse);
  913.         DisposePtr((Ptr) refNums);
  914.         if (refNumCount == 0)
  915.             return kODFalse;
  916.     }
  917.         
  918.     AppleEvent    activateEvent, reply;
  919.     AEDesc        addressDesc = {typeNull, kODNULL};
  920.     ProcessSerialNumber psn = {0,kNoProcess};
  921.     ProcessInfoRec aProcess;
  922.     
  923. //    DisposePtr((Ptr) refNums);        // <eeh> why doesn't this come before the return above?
  924.     // create the activate event
  925.     CHECKR(AECreateAppleEvent(kAEOpenDocSuite, kODActivateEvent, &addressDesc, 
  926.                 kAutoGenerateReturnID, kAnyTransactionID, &activateEvent)
  927.             , kODTrue);
  928.  
  929.     err = AEPutParamPtr(&activateEvent, keyDirectObject, typeFSS, 
  930.                                         (Ptr) fileSpec, sizeof(*fileSpec));
  931.     if (err != noErr)
  932.     {
  933.         AEDisposeDesc(&activateEvent);
  934.         return kODTrue;
  935.     }
  936.  
  937.     err = AEPutParamPtr(&activateEvent, keyODActivateEventCause, typeType, 
  938.                                         (Ptr)&eventID, sizeof(eventID));
  939.     if (err != noErr)
  940.     {
  941.         AEDisposeDesc(&activateEvent);
  942.         return kODTrue;
  943.     }
  944.     
  945.     if ( refnumForResFork )
  946.     {
  947.         err = AEPutParamPtr( &activateEvent, keyODRefnumFromResource,
  948.                 typeBoolean, (Ptr)&refnumForResFork,
  949.                 sizeof(refnumForResFork) );
  950.         if (err != noErr)
  951.         {
  952.             AEDisposeDesc(&activateEvent);
  953.             return kODTrue;
  954.         }
  955.     }
  956.  
  957.     // send the activate event to all OpenDoc processes
  958.     aProcess.processInfoLength = sizeof(ProcessInfoRec);
  959.     aProcess.processName = kODNULL;
  960.     aProcess.processAppSpec = kODNULL;
  961.     
  962.     while (GetNextProcess(&psn) == noErr)
  963.         if (GetProcessInformation(&psn, &aProcess) == noErr)
  964.             if (aProcess.processType != 'APPL' &&
  965.                 aProcess.processSignature == kODShellSignature)
  966.             {
  967.                 CHECKR(
  968.                     AECreateDesc(typeProcessSerialNumber, (Ptr) &psn, sizeof(psn),
  969.                                  &addressDesc)
  970.                     , kODTrue);
  971.  
  972.                 CHECKR(AEPutAttributeDesc(&activateEvent, keyAddressAttr, &addressDesc)
  973.                         , kODTrue);
  974.                 CHECKR(AESend(&activateEvent, &reply, kAENoReply, kAENormalPriority,
  975.                                 kAEDefaultTimeout, kODNULL, kODNULL)
  976.                         , kODTrue);
  977.                 // this shouldn't error since the handler always returns noErr
  978.                 // ASSERT that reply == {typeNull, 0}
  979.  
  980.                 CHECKR(AEDisposeDesc(&addressDesc), kODTrue);
  981.             }
  982.     err = AEDisposeDesc(&activateEvent);
  983.     return kODTrue;
  984. }
  985.  
  986. //==============================================================================
  987. // VerifyAndLaunchDocumentStub
  988. //==============================================================================
  989.  
  990. OSErr VerifyAndLaunchDocumentStub(AEDesc *theDocument, AEDescList* otherParams,
  991.         ProcessSerialNumber *psn, DescType eventID, FSSpec* seedFSSPtr)
  992. {
  993.     // if the document isn't local or can't be written to, make a local stub
  994.     // in temp items folder.
  995.     
  996.     FSSpec documentStub;
  997.     FSSpec documentSpec;
  998.     DocStubType isDuplicate;
  999.     OSErr err;
  1000.  
  1001.     err = MakeDocumentStub(theDocument, &documentStub, &documentSpec,
  1002.                             &isDuplicate, eventID);
  1003.     if (isDuplicate == kIsAlreadyLaunched)
  1004.         return err;
  1005.         
  1006.     if (!err)
  1007.     {
  1008.         err = VerifyDocumentStub(&documentStub, seedFSSPtr);
  1009.         if (!err && documentStub.name[0]!=0) {
  1010.             // need to get the alias here rather than coerce in LaunchDocument,
  1011.             // as the AEM can't coerce FSS->Alias, at least when AOCE docs are
  1012.             // involved.
  1013.             // $Opt: Remove alias stuff if unnecessary for non AOCE docs.
  1014.             AEDesc theAlias;
  1015.             OSErr aliasErr = 1;            // so won't pass test below unless set
  1016.             if (isDuplicate == kIsSameAsStub)
  1017.                 aliasErr = NewAliasMinimal(&documentStub,
  1018.                         (AliasHandle *)&theAlias.dataHandle);
  1019.     
  1020.             if (seedFSSPtr == kODNULL ||
  1021.                 seedFSSPtr->vRefNum != documentStub.vRefNum ||
  1022.                 seedFSSPtr->parID != documentStub.parID ||
  1023.                 seedFSSPtr->name[0] != documentStub.name[0])
  1024.             {
  1025.                 if (!aliasErr) {
  1026.                     theAlias.descriptorType = typeAlias;
  1027.                     err= LaunchDocumentStub(theDocument, &documentStub, &theAlias,
  1028.                         otherParams, psn, eventID);
  1029.                     AEDisposeDesc(&theAlias);
  1030.                 } else
  1031.                     err= LaunchDocumentStub(theDocument, &documentStub, kODNULL,
  1032.                         otherParams, psn, eventID);
  1033.             }
  1034.         }
  1035.     }
  1036.     return err;
  1037. }
  1038.  
  1039. //==============================================================================
  1040. // TestAndUpdate
  1041. //==============================================================================
  1042.  
  1043. static OSErr GetPrefsFileSpec(ODFileSpec* prefFileSpec)
  1044. {
  1045.     CInfoPBRec        pb;
  1046.     memset (&pb,0,sizeof(pb));
  1047.  
  1048.     FindFolder(kOnSystemDisk, kPreferencesFolderType, kCreateFolder, 
  1049.                             &pb.dirInfo.ioVRefNum, &pb.dirInfo.ioDrDirID);
  1050.     StringHandle prefsFileName = GetString( kSHLPrefsFileNameResID );
  1051. #if ODDebug
  1052.     if ( !prefsFileName )
  1053.         DebugStr( "\pcouldn't find kSHLPrefsFileNameResID str resource" );
  1054. #endif
  1055.     StringHandle prefsFolderName = GetString( kSHLPrefsFolderNameResID );
  1056.     //ODGetString(prefFolderName,kODPrefsFolderNameStrID);
  1057.  
  1058.     Str63 name; //must be an array because sizeof depends on it below
  1059.     //CopyPascalString(name,*prefsFolderName);
  1060.     BlockMove(*prefsFolderName,name,sizeof(name));    
  1061.     
  1062.     pb.dirInfo.ioNamePtr = name;
  1063.     pb.dirInfo.ioFDirIndex = 0;
  1064.     OSErr result = PBGetCatInfoSync( &pb );
  1065.     if (result == noErr)
  1066.     {
  1067.         if( pb.hFileInfo.ioFlFndrInfo.fdFlags & kIsAlias ) {
  1068.             FSSpec spec;
  1069.             ODBoolean targetIsFolder, wasAliased;
  1070.             FSMakeFSSpec(pb.dirInfo.ioVRefNum,pb.dirInfo.ioDrParID,name, &spec);
  1071.             result =  ResolveAliasFile(&spec, kODTrue, &targetIsFolder, &wasAliased);
  1072.             if (result == noErr)
  1073.             {
  1074.                 if( !targetIsFolder )
  1075.                     result = dirNFErr;
  1076.                 // Now get dir ID of target folder:
  1077.                 pb.dirInfo.ioNamePtr = spec.name;
  1078.                 pb.dirInfo.ioFDirIndex = 0;
  1079.                 pb.dirInfo.ioVRefNum = spec.vRefNum;
  1080.                 pb.dirInfo.ioDrDirID = spec.parID;
  1081.                 result = PBGetCatInfoSync( &pb );
  1082.             }
  1083.         }
  1084.     
  1085.         if (result == noErr)
  1086.         {
  1087.             FSMakeFSSpec(pb.dirInfo.ioVRefNum, pb.dirInfo.ioDrDirID, *prefsFileName, prefFileSpec);
  1088.             ReleaseResource( (Handle)prefsFileName );
  1089.             ReleaseResource( (Handle)prefsFolderName );
  1090.         }
  1091.     }
  1092.     return result;
  1093. }
  1094.  
  1095.  
  1096. static ODHandle GetPrefSizeResource()
  1097. {
  1098.     ODHandle prefSize = kODNULL;
  1099.     short theCurResFile = CurResFile();
  1100.     // Code partially copied from Prefs.cpp, should probably call a common util function
  1101.     ODFileSpec        prefFileSpec;
  1102.     OSErr result = GetPrefsFileSpec(&prefFileSpec);
  1103.     if (result == noErr)
  1104.     {
  1105.         ODSShort         prefResFile;
  1106.         prefResFile = FSpOpenResFile((const FSSpec *)&prefFileSpec,fsRdPerm);
  1107.         
  1108.         if (prefResFile != -1)
  1109.         {
  1110.             prefSize = Get1Resource(kSIZERsrcType, kSIZEID);
  1111.             if (prefSize)
  1112.                 DetachResource(prefSize);
  1113.             CloseResFile( prefResFile );
  1114.             UseResFile(theCurResFile);
  1115.         }
  1116.     }
  1117.     return prefSize;
  1118. }
  1119.  
  1120.  
  1121. // Check the doc's resource against the original copy.
  1122. static OSErr TestAndUpdate(Handle origRsrc,ResType rtype,short rid)
  1123. {
  1124.     // For SIZE-1, we need to check to see if there is an override in OpenDoc Prefs
  1125.     ODHandle prefSize = kODNULL;
  1126.     if (rtype == kSIZERsrcType && rid == kSIZEID)
  1127.     {
  1128.         prefSize = GetPrefSizeResource();
  1129.         if (prefSize != kODNULL)
  1130.             origRsrc = prefSize;
  1131.     }
  1132.     
  1133.     Handle docRsrc = Get1Resource(rtype, rid);
  1134.     
  1135.     if (docRsrc) 
  1136.     {
  1137.         // Doc has resource. Compare data and possibly update:
  1138.         Size origSize = GetHandleSize(origRsrc);
  1139.         if (GetHandleSize(docRsrc)!=origSize
  1140.                             || ODXmemcmp(*origRsrc,*docRsrc,origSize)!=0) 
  1141.         {
  1142.             SetHandleSize(docRsrc, origSize);            // Rsrc contents are different
  1143.             if (MemError()) return MemError();
  1144.             BlockMove(*origRsrc,*docRsrc,origSize);        // so copy over the original data
  1145.             ChangedResource(docRsrc);
  1146.             return ResError();
  1147.         }
  1148.         else
  1149.         {
  1150.             return noErr;
  1151.         }
  1152.             
  1153.     } 
  1154.     else 
  1155.     {
  1156.         OSErr err= ResError();
  1157.         if (err!=noErr && err!=resNotFound)
  1158.             return err;                                    // Something bad happened...
  1159.             
  1160.         // No such rsrc in document, so add one:
  1161.         docRsrc = origRsrc;
  1162.         err= HandToHand(&docRsrc);
  1163.         if (err) return err;
  1164.         AddResource(docRsrc,rtype,rid,nil);
  1165.         return ResError();
  1166.     }
  1167.     if (prefSize != kODNULL)
  1168.         DisposeHandle(prefSize);
  1169. }
  1170.  
  1171.  
  1172. //==============================================================================
  1173. // VerifyDocument
  1174. //==============================================================================
  1175.  
  1176. OSErr VerifyDocumentStub(FSSpec *theStub, FSSpec* seedFSSPtr)
  1177. {
  1178. // VerifyDocumentStub precondition: theStub is writable or it is an OpenDoc Editor
  1179. // All resources are verified on both 68K & PPC.
  1180. // if the FSSpec passed in is an OpenDoc Editor
  1181. // then we create a stationery pad seed file and
  1182. //  munge the FSSpec to point to it instead
  1183.  
  1184.     // First, grab my original copies of the rsrcs to be stuffed into the document:
  1185.     Handle origRsrc[kNumDocStubRsrcs] = { kODNULL, kODNULL, kODNULL, kODNULL };
  1186.         
  1187.     OSErr err = noErr;
  1188.     ODUShort i = 0;
  1189.     do {
  1190.         origRsrc[i] = GetResource(docStubRsrcType[i],docStubRsrcID[i]);
  1191.     } while (origRsrc[i] != kODNULL && ++i<kNumDocStubRsrcs);
  1192.         
  1193.     if (i != kNumDocStubRsrcs)
  1194.         return ResError() ? ResError() :resNotFound;        // Some resource is missing
  1195.  
  1196.     // If we are opening a shared library, create a stationery seed file:
  1197.     FInfo finderInfo;
  1198.     FSpGetFInfo(theStub,&finderInfo);
  1199.     if (finderInfo.fdType == kEditorFileType) 
  1200.     {
  1201.         CHECK(CreateStationerySeed(theStub, seedFSSPtr));
  1202.     } 
  1203.     else if (finderInfo.fdType == kPrefFileType) 
  1204.     {
  1205.         theStub->name[0] = 0;
  1206.         Str255 s;
  1207.         GetIndString(s, kODXLibsFldrStrID, 2);
  1208.         if (s[0])
  1209.         {
  1210.             ParamText(s,"\p","\p","\p");
  1211.             NoteAlert(2001,NULL);
  1212.         }
  1213.         return noErr;
  1214.     }
  1215.     else if (finderInfo.fdType == 'APPL')
  1216.     {
  1217.         theStub->name[0] = 0;
  1218.     }
  1219.     
  1220.  
  1221.     if (theStub->name[0] == 0)  // File was non-Editor shared library, or unable to create stub
  1222.         return noErr;
  1223.         
  1224.     // Now open (or create) the document's resource fork:
  1225.     short theCurResFile = CurResFile();
  1226.     short docRefNum = FSpOpenResFile(theStub,fsRdWrPerm);
  1227.     if ((err = ResError()) != noErr)
  1228.     {
  1229.         // Need to create resource fork if there is none:
  1230.         if (err == eofErr)
  1231.         {
  1232.             // If other than eofErr, something's wrong
  1233.             // would have expected fnfErr. 
  1234.             // if the create fails, we might try settting the eof to 0.
  1235.             // and trying the create again
  1236.             FSpCreateResFile(theStub,finderInfo.fdCreator,finderInfo.fdType,smSystemScript);
  1237.             if ((err = ResError()) == noErr)
  1238.             {
  1239.                 docRefNum = FSpOpenResFile(theStub,fsRdWrPerm);
  1240.                 err = ResError();
  1241.             }
  1242.         }
  1243.         if (err != noErr)
  1244.             return err;
  1245.     }
  1246.  
  1247.     // Finally, verify, add, and/or update the document resources:
  1248.     for (i = 0; i<kNumDocStubRsrcs && err==noErr; ++i)
  1249.     {
  1250.         err = TestAndUpdate(origRsrc[i],copiedRsrcType[i],copiedRsrcID[i]);
  1251.     }
  1252.     
  1253.     // Clean up our toys and go home:
  1254.     CloseResFile(docRefNum);
  1255.     if (!err)
  1256.         err= ResError();
  1257.         
  1258.     UseResFile(theCurResFile);
  1259.     
  1260.     return err;
  1261. }
  1262.  
  1263.  
  1264. //==============================================================================
  1265. // CreateStationerySeed
  1266. //==============================================================================
  1267.  
  1268. static OSErr CreateStationerySeed(FSSpec *theDocument, FSSpec* seedFSSPtr)
  1269. {
  1270.     // note that coming in, theDocument is actually the Editor library;
  1271.     // going out, theDocument is the newly created Stationery Seed
  1272.     // seedFSSPtr is used if already set (name[0]≠0), else it is filled in.
  1273.     // IF seedFSSPtr is NOT filled in, then theDocument name is set to null.
  1274.  
  1275.     OSErr err = noErr;
  1276.     ODEditor   editorID = kODNULL;
  1277.     EditorUserStringList*    editorUsrStrgPairs = kODNULL;
  1278.     ODUShort editorCount = 0;
  1279.     EditorUserStringList* pair = kODNULL;
  1280.     
  1281. // First, read in the editorUserString NMAP from the Editor library
  1282.     short saveResFile = CurResFile();
  1283.     short resRefNum = FSpOpenResFile(theDocument,fsRdPerm);
  1284.     if ((err = ResError()) != noErr)
  1285.         return err;
  1286.     
  1287.     err = GetEditorUserStringPairs(resRefNum, &editorUsrStrgPairs, &editorCount);
  1288.     CloseResFile(resRefNum);
  1289.     UseResFile(saveResFile);
  1290.     if (err != noErr)
  1291.         return err;
  1292.  
  1293.     if (editorCount == 0)
  1294.     {
  1295.         theDocument->name[0] = 0;
  1296.         return noErr;
  1297.     }
  1298.     
  1299. // Loop through the list of editor/editorUserString pairs 
  1300. //    (libraries may contain more than one editor)
  1301.  
  1302.     for (pair = editorUsrStrgPairs;
  1303.             pair;
  1304.             pair = pair->next)
  1305.     {
  1306.         long length = pair->editor[0];
  1307.         Handle editor = NewHandleClear(1+length);
  1308.         if (MemError())
  1309.             return MemError();
  1310.         HLock(editor);
  1311.         BlockMove((Ptr)&pair->editor[1], (Ptr)*editor, length);
  1312.         HUnlock(editor);
  1313.         Str255 editorName;
  1314.         editorName[0] = pair->name.theText[0];
  1315.         BlockMove((Ptr)&pair->name.theText[1], (Ptr)&editorName[1], editorName[0]);
  1316.  
  1317.         if (seedFSSPtr != kODNULL && seedFSSPtr->name[0] != 0)
  1318.         {
  1319.             *theDocument = *seedFSSPtr;
  1320.         }
  1321.         else
  1322.         {
  1323.             // Create the stationery seed.  Note: this file is NOT user visible!
  1324.             // I.e. Don't have a cow about the hard coded string.
  1325.             CreateUniqueTmpFolderForFile(theDocument, "\pStationery Seed");
  1326.             FSpCreateResFile(theDocument,kODShellSignature,kODShellSignature,smSystemScript);
  1327.             CHECK(ResError());
  1328.             if (seedFSSPtr != kODNULL)
  1329.                 *seedFSSPtr = *theDocument;
  1330.         }
  1331.         
  1332.     // Plant the 'seed' resource
  1333.         saveResFile = CurResFile();
  1334.         ODSShort    seedRefNum;
  1335.         seedRefNum = FSpOpenResFile(theDocument,fsRdWrPerm);
  1336.         CHECK(ResError());
  1337.         
  1338.         AddResource(editor, kDocSeedResType, Unique1ID(kDocSeedResType), editorName);
  1339.         err= ResError();
  1340.         CloseResFile(resRefNum);
  1341.         UseResFile(saveResFile);
  1342.     }
  1343.  
  1344.     for (pair = editorUsrStrgPairs;
  1345.         pair;)
  1346.     {
  1347.         EditorUserStringList* nextPair = pair->next;
  1348.         DisposePtr( (Ptr)pair );
  1349.         pair = nextPair;
  1350.     }
  1351.     return err;
  1352. }
  1353.  
  1354. //==============================================================================
  1355. // string stuff
  1356. //==============================================================================
  1357.  
  1358. static char ODXmemcmp(char* buffer1,char* buffer2,unsigned int len)
  1359. {
  1360.   while (len-- > 0)
  1361.       if (*buffer1++ != *buffer2++)
  1362.           return (*--buffer1)-(*--buffer2);
  1363.   return 0;
  1364. }
  1365.  
  1366. static size_t    ODXstrlen(const char *s)
  1367. {
  1368.     size_t len = 0;
  1369.     while (*s++) ++len;
  1370.     return len;
  1371. }
  1372.  
  1373. static char*     ODXstrncpy(char* destStr, char* srcStr, size_t n)
  1374. {
  1375.     char* ret = destStr;
  1376.     while (n-- > 0)
  1377.         if ((*destStr++ = *srcStr++) == 0)
  1378.         {
  1379.             while (n-- > 0)
  1380.                 *destStr++ = '\0';
  1381.                 
  1382.             break;
  1383.         }
  1384.         
  1385.     return ret;    
  1386. }
  1387.  
  1388. static char*     ODXstrncat(char* destStr, char* srcStr, size_t n)
  1389. {
  1390.     size_t len = ODXstrlen(destStr);
  1391.     destStr += len;
  1392.     return ODXstrncpy(destStr, srcStr, n);
  1393. }
  1394.  
  1395.  
  1396. //==============================================================================
  1397. // Launching the document process
  1398. //==============================================================================
  1399.  
  1400. //==============================================================================
  1401. // LaunchDocumentStub
  1402. //==============================================================================
  1403.  
  1404. OSErr LaunchDocumentStub(AEDesc* theDocument, FSSpec *documentStub,
  1405.         AEDesc* theAlias, AEDescList* otherParams, ProcessSerialNumber *psn,
  1406.         DescType eventID)
  1407. {
  1408.     // This routine will leave stuff behind if it encounters an error, since there
  1409.     // is no cleanup of the stuff that it allocates. This should not be a problem since
  1410.     // we are going to quit soon anyway. Right? --jpa.  
  1411.     // No, we are NOT going to quit soon when for example you do a
  1412.     // "New" or "Open Document…". -TÇ.
  1413.     
  1414.     ODUnused(otherParams);
  1415.     
  1416.     LaunchParamBlockRec    launchPB;
  1417.     OSErr                err;
  1418.  
  1419.     launchPB.launchBlockID = extendedBlock;
  1420.     launchPB.launchEPBLength = extendedBlockLen;
  1421.     launchPB.launchControlFlags = launchContinue | launchNoFileFlags;
  1422.     launchPB.launchAppSpec = documentStub;
  1423.  
  1424.     AEDesc launchDesc;
  1425.     AEDescList theList;
  1426.     AppleEvent theEvent;
  1427.     AEDesc myAddress;
  1428.     myAddress.descriptorType = nil;
  1429.     myAddress.dataHandle = nil;
  1430.     
  1431.     CHECK(AECreateAppleEvent(kCoreEventClass, eventID, &myAddress,
  1432.                         kAutoGenerateReturnID, kAnyTransactionID, &theEvent));
  1433. //    if (otherParams)
  1434. //        CHECK(AEPutParamDesc(&theEvent, kKeySpecialParams, otherParams));
  1435.  
  1436.     CHECK(AECreateList(nil,0,false,&theList));
  1437.     if (theAlias)
  1438.         CHECK(AEPutDesc(&theList, 0, theAlias));
  1439.     else
  1440.         CHECK(AEPutDesc(&theList, 0, theDocument));
  1441.     CHECK(AEPutParamDesc(&theEvent, keyDirectObject, &theList));
  1442.  
  1443.     CHECK(AECoerceDesc(&theEvent, typeAppParameters, &launchDesc));
  1444. /*
  1445.     This may look a little weird, since we're actually moving the event out of the
  1446.     AppParameters descriptor.  But it's necessary, the coercison to typeAppParameters
  1447.     takes the 'aevt' and puts it all in one handle, instead of
  1448.     leaving it as a AEDesc.  So, only one handle is being added to
  1449.     the launch parameter block instead of an AEDesc.
  1450. */
  1451.     HLock(launchDesc.dataHandle);
  1452.     launchPB.launchAppParameters = (AppParametersPtr)*(launchDesc.dataHandle);
  1453.  
  1454. #if defined(powerc) || defined(__powerc)
  1455. #else
  1456.     FlushInstructionCache();
  1457.     FlushDataCache();
  1458. #endif
  1459.  
  1460.     err= LaunchApplication(&launchPB);
  1461.     
  1462.     if (psn)
  1463.         *psn = launchPB.launchProcessSN;
  1464.     
  1465.     return err;
  1466. }
  1467.  
  1468.  
  1469. void
  1470. GetLaunchFailedParams(AppleEvent *ae, long &launchError, ProcessSerialNumber *psn,
  1471.                                         Str255 appName, Str255 libName)
  1472. {
  1473.     OSErr err;
  1474.     DescType type;
  1475.     Size size;
  1476.     
  1477.     err= AEGetParamPtr(ae,keyErrorNumber,typeLongInteger,&type,
  1478.                             &launchError,sizeof(launchError), &size);
  1479.     if (err)
  1480.         launchError = err;
  1481.         
  1482.     if (psn!=NULL) {
  1483.         psn->lowLongOfPSN = 0;
  1484.         psn->highLongOfPSN = 0;
  1485.         (void) AEGetParamPtr(ae,keyProcessSerialNumber,typeProcessSerialNumber,&type,
  1486.                             psn,sizeof(*psn), &size);
  1487.     }
  1488.     
  1489.     err= AEGetParamPtr(ae,'APPL',typeChar,&type, &appName[1],255, &size);
  1490.     appName[0] = err ?0 :size;
  1491.     
  1492.     err= AEGetParamPtr(ae,'LIBN',typeChar,&type, &libName[1],255, &size);
  1493.     libName[0] = err ?0 :size;
  1494. }
  1495.  
  1496. ODBoolean myEqualPascalStrings(ConstStr255Param str1, ConstStr255Param str2)
  1497. {
  1498.     if (str1[0] != str2[0])
  1499.         return kODFalse;
  1500.     for (int i = 1; i <= str1[0]; i++)
  1501.     {
  1502.         if (str1[i] != str2[i])
  1503.             return kODFalse;
  1504.     }
  1505.     return kODTrue;
  1506. }
  1507.  
  1508.  
  1509. /*
  1510. **    Apple Macintosh Developer Technical Support
  1511. **
  1512. **    File:    GetLocalPaths.c
  1513. **
  1514. **    by Jim Luther, Apple Developer Technical Support
  1515. **
  1516. **    Copyright © 1995 Apple Computer, Inc.
  1517. **    All rights reserved.
  1518. */
  1519.  
  1520.  
  1521. pascal    OSErr    GetLocalPaths(FSSpec *spec,
  1522.                               ForkType fork,
  1523.                               unsigned long *refNumCount,
  1524.                               RefNumPtr *refNums)
  1525. {
  1526.     enum
  1527.     {
  1528.         kMaxFCBs = 348    /* The maximum number of local access paths under System 7 */
  1529.     };
  1530.     
  1531.     OSErr        result;
  1532.     FCBPBRec    pb;
  1533.     short        index;
  1534.     Str31        tempName;
  1535.     RefNumPtr    tempRefNums;
  1536.     
  1537.     /* initialize returned values */
  1538.     *refNumCount = 0;
  1539.     *refNums = NULL;
  1540.     
  1541.     /* Allocate temp storage for refNum matches */
  1542.     tempRefNums = (RefNumPtr)NewPtr(kMaxFCBs * sizeof(short));
  1543.     
  1544.     if ( tempRefNums != NULL )
  1545.     {
  1546.         /* Get FCB name in tempName */
  1547.         pb.ioNamePtr = tempName;
  1548.         
  1549.         /* Index through the open paths on the volume specified by spec->vRefNum */
  1550.         pb.ioVRefNum = spec->vRefNum;
  1551.         index = 1;
  1552.         do
  1553.         {
  1554.             pb.ioRefNum = 0;
  1555.             pb.ioFCBIndx = index;
  1556.             result = PBGetFCBInfoSync(&pb);
  1557.             if ( result == noErr )
  1558.             {
  1559.                 /*
  1560.                 **    See if parent directory ID matches and
  1561.                 **    file name matches and
  1562.                 **    the file fork (resource or data) matches
  1563.                 */
  1564.                 if ( (pb.ioFCBParID == spec->parID) &&
  1565.                      EqualString(spec->name, tempName, false, true) &&
  1566.                      ((fork == kResourceFork) == ((pb.ioFCBFlags & (1 << 9)) != 0)) )
  1567.                 {
  1568.                     /* It's a match - add it to the array of matches */
  1569.                     tempRefNums[*refNumCount] = pb.ioRefNum;
  1570.                     ++(*refNumCount);
  1571.                 }
  1572.                 ++index;    /* next FCB index */
  1573.             }
  1574.         } while ( result == noErr );
  1575.         
  1576.         /* These errors are OK - they mean we hit the end of the FCB list */
  1577.         if ( (result == rfNumErr) || (result == fnOpnErr) )
  1578.         {
  1579.             result = noErr;
  1580.         }
  1581.         
  1582.         if ( (result == noErr) && (*refNumCount != 0) )
  1583.         {
  1584.             /* Allocate memory to return refNum matches in */
  1585.             *refNums = (RefNumPtr)NewPtr(*refNumCount * sizeof(short));
  1586.             if ( *refNums != NULL )
  1587.             {
  1588.                 /* Move refNums from tempRefNums to *refNums */
  1589.                 BlockMoveData((Ptr)tempRefNums, (Ptr)*refNums, (*refNumCount * sizeof(short)));
  1590.             }
  1591.             else
  1592.             {
  1593.                 /* Couldn't allocate memory for refNum array */
  1594.                 result = memFullErr;
  1595.             }
  1596.         }
  1597.         
  1598.         /* Free up tempRefNums storage */ 
  1599.         DisposePtr((Ptr)tempRefNums);
  1600.     }
  1601.     else
  1602.     {
  1603.         /* Couldn't allocate temp memory */
  1604.         result = memFullErr;
  1605.     }
  1606.     
  1607.     return ( result );
  1608. }
  1609.  
  1610. //------------------------------------------------------------------------------
  1611. // GetEditorUserStringPairs
  1612. //------------------------------------------------------------------------------
  1613.  
  1614. OSErr GetEditorUserStringPairs(ODSShort resRefNum, 
  1615.                             EditorUserStringList** pairs, ODUShort* editorCount)
  1616. {
  1617.     Handle         theEdtrUSnmap = kODNULL;
  1618.     *editorCount = 0;
  1619.     ODError result = noErr;
  1620.     
  1621.     if( resRefNum != -1 ) {
  1622.         ODSShort nmapCount = Count1Resources( kODNameMappings );
  1623.         if ((result = ResError()) != noErr)
  1624.             return result;
  1625.             
  1626.         for (short i=1; i<=nmapCount; i++) 
  1627.         {
  1628.                 // Get the Resource
  1629.             ODHandle nmap = (ODHandle)Get1IndResource(kODNameMappings, i);
  1630.             if ((result = ResError()) != noErr)
  1631.                 return result;
  1632.             
  1633.             if ( nmap != nil && !result  )
  1634.             {
  1635.                 HLock((ODHandle) nmap);
  1636.  
  1637.                 result = GetEditorSetFromNMAP(nmap, pairs, editorCount);
  1638.                                          
  1639.                 ReleaseResource( nmap );
  1640.             }
  1641.             
  1642.             if ((*editorCount > 0) || (result != 0))
  1643.                 break;
  1644.         }
  1645.     }
  1646.     return result;
  1647. }
  1648.  
  1649. //------------------------------------------------------------------------------
  1650. // GetEditorSetFromNMAP
  1651. //------------------------------------------------------------------------------
  1652.  
  1653. OSErr GetEditorSetFromNMAP( ODHandle nmap, EditorUserStringList** pairs, 
  1654.                                                          ODUShort* editorCount )
  1655. {
  1656.     ODISOStr        nameSpaceName = kODNULL; ODVolatile(nameSpaceName);
  1657.     ODUShort        nameLen;
  1658.     ODUShort        editorLen;
  1659.     ODSize            bufferPos=(ODSize)*nmap;
  1660.     ODSize            sizeShort = sizeof(ODUShort);
  1661.     OSErr            result = noErr;
  1662.     
  1663.     BlockMove((ODPtr)bufferPos, (ODPtr)&nameLen, sizeShort);
  1664.     bufferPos += sizeShort;
  1665.  
  1666.     nameSpaceName = (ODISOStr)NewPtrClear((ODSize)nameLen+1);
  1667.     if (!nameSpaceName)
  1668.         result = memFullErr;
  1669.     else
  1670.     {
  1671.         BlockMove((ODPtr)bufferPos, (ODPtr)nameSpaceName, (ODSize)nameLen);
  1672.         bufferPos += (ODSize)nameLen;
  1673.         
  1674.         if (!ODXmemcmp(nameSpaceName,kODEditorUserString,ODXstrlen(kODEditorUserString)))
  1675.         {
  1676.             BlockMove((ODPtr)bufferPos,(ODPtr)editorCount, sizeShort);
  1677.             bufferPos += sizeShort;
  1678.             
  1679.             if ( *editorCount > 0 )
  1680.             {
  1681.     
  1682.                 *pairs = (EditorUserStringList*)NewPtrClear(
  1683.                                               sizeof(EditorUserStringList));
  1684.                 if (!*pairs)
  1685.                     result = memFullErr;
  1686.                 else
  1687.                 {
  1688.                     EditorUserStringList* thisPair = *pairs;
  1689.                     
  1690.                     for(ODUShort i=0; i < *editorCount && thisPair; i++)
  1691.                     {
  1692.                         BlockMove((ODPtr)bufferPos,(ODPtr)&editorLen,sizeShort);
  1693.                         bufferPos += sizeShort;
  1694.                         
  1695.                         thisPair->editor[0] = editorLen;
  1696.                         BlockMove((ODPtr)bufferPos,(ODPtr)&thisPair->editor[1],
  1697.                                                          (ODSize)editorLen);
  1698.                         bufferPos += (ODSize)editorLen;
  1699.                         bufferPos += sizeShort;
  1700.                                         
  1701.                             // read UserString from the nmap
  1702.                         BlockMove((ODPtr)bufferPos, 
  1703.                             (ODPtr)&thisPair->name.theScriptCode,sizeof(ScriptCode));
  1704.                         bufferPos += sizeof(ScriptCode);
  1705.                         BlockMove((ODPtr)bufferPos, 
  1706.                             (ODPtr)&thisPair->name.theLangCode,sizeof(LangCode));
  1707.                         bufferPos += sizeof(LangCode);
  1708.                         BlockMove((ODPtr)bufferPos,(ODPtr)&nameLen,sizeShort);
  1709.                         bufferPos += sizeShort;
  1710.                         thisPair->name.theText[0] = nameLen;
  1711.                         BlockMove((ODPtr)bufferPos,(ODPtr)&thisPair->name.theText[1], nameLen);
  1712.                         bufferPos += nameLen;
  1713.                         
  1714.                         if (i+1 < *editorCount )
  1715.                         {
  1716.                             thisPair->next = (EditorUserStringList*)NewPtrClear(
  1717.                                               sizeof(EditorUserStringList));
  1718.                             thisPair = thisPair->next;
  1719.                             if (!thisPair)
  1720.                                 result = memFullErr;
  1721.  
  1722.                         }
  1723.                     }
  1724.                 }
  1725.             }
  1726.         }
  1727.     }
  1728.  
  1729.     DisposePtr(nameSpaceName);
  1730.     return result;
  1731. }
  1732.  
  1733. //------------------------------------------------------------------------------
  1734. // MoveToTrash -- $$$$$ duplicated from Prefs.cpp
  1735. //------------------------------------------------------------------------------
  1736. static void
  1737. MoveToTrash( short vRefnum, long dirID, Str255 name )
  1738. {
  1739.     short foundVRefNum;
  1740.     long  foundDirID;
  1741.     
  1742.     if(!FindFolder(vRefnum, kTrashFolderType, kDontCreateFolder, 
  1743.                                 &foundVRefNum, &foundDirID))
  1744.     {
  1745.  
  1746.         CMovePBRec paramBlock ;
  1747.         memset( ¶mBlock, 0, sizeof(paramBlock) );
  1748.         
  1749.         paramBlock.ioNamePtr = name ;
  1750.         paramBlock.ioVRefNum = foundVRefNum ;
  1751.         paramBlock.ioNewDirID = foundDirID ;
  1752.         paramBlock.ioDirID = dirID ;
  1753.         
  1754.         (void) HDelete(foundVRefNum,foundDirID,name);     // ignore error (may not exist)
  1755.         OSErr result = PBCatMoveSync( ¶mBlock );
  1756.         if (result)
  1757.             (void) HDelete(vRefnum,dirID,name); 
  1758.     }
  1759.     else
  1760.         (void) HDelete(vRefnum,dirID,name); 
  1761. }
  1762.  
  1763.  
  1764. //------------------------------------------------------------------------------
  1765. // ShowAboutScreen
  1766. //------------------------------------------------------------------------------
  1767.  
  1768. static short    GetMainDeviceDepth(void)
  1769. {
  1770.     GDHandle        device;
  1771.     short            depth;
  1772.     PixMapHandle    pmap;
  1773.     
  1774.     depth  = 1;
  1775.     device = GetMainDevice();
  1776.     if (
  1777.         (TestDeviceAttribute(device, screenDevice)) &&
  1778.         (TestDeviceAttribute(device, screenActive))
  1779.     ) {
  1780.         pmap  = (*device)->gdPMap;
  1781.         depth = (*pmap)->pixelSize;
  1782.     }
  1783.     
  1784.     return(depth);
  1785. }
  1786.  
  1787. const short kSplashDlogID            = kODSplashDlogID;
  1788. const short kSplashDefaultPICTID    = 131;
  1789. const short kSplashBWPICTID            = 132;
  1790. const short kSplash16PICTID            = 133;
  1791. const short kSplashBestPICTID        = 134;
  1792.  
  1793.  
  1794. DialogPtr ShowAboutScreen( )
  1795. {
  1796.     DialogPtr aboutScreen = NULL;
  1797.     short depth = GetMainDeviceDepth();
  1798.     
  1799.     short pictID = kSplashDefaultPICTID;
  1800.  
  1801.     Str255 s255; s255[0]=0;
  1802.     WindowPtr ww = FrontWindow();
  1803.     if (ww)
  1804.         GetWTitle(ww, s255);
  1805.     else
  1806.         BlockMove(LMGetCurApName(), s255, 32);
  1807.         
  1808.     if (!EqualString(s255, "\pAbout OpenDoc...", TRUE, FALSE))
  1809.     // Note, the above string is NEVER user visible, so there is no need
  1810.     // to worry about localizing it.
  1811.     
  1812.     switch (depth) {
  1813.     case 1:
  1814.         pictID = kSplashBWPICTID; break;
  1815.     case 4:
  1816.         pictID = kSplash16PICTID; break;
  1817.     default:
  1818.         pictID = kSplashBestPICTID; break;
  1819.     }
  1820.     
  1821.     if( Get1Resource('DLOG',kSplashDlogID) )
  1822.         aboutScreen = GetNewDialog(kSplashDlogID,NULL,(WindowPtr)-1L);
  1823.     if( aboutScreen ) {
  1824.         short        itemHit;
  1825.         Handle        scratchHandle = kODNULL;
  1826.         Rect        itemRect;
  1827.     
  1828.         GetDialogItem(aboutScreen, 1, &itemHit, &scratchHandle, &itemRect);
  1829.         
  1830.         PicHandle pictHandle = (PicHandle)Get1Resource('PICT', pictID);
  1831.         
  1832.         TEHandle te = ((DialogPeek)aboutScreen)->textH;
  1833.         (**te).just = teJustCenter;
  1834.         
  1835.         struct VersRsrc {
  1836.             long    versJunk;
  1837.             short    region;
  1838.             Str255    versionStr;
  1839.         };
  1840.         VersRsrc **vers = (VersRsrc**) Get1Resource('vers',2);
  1841.         if( vers ) {
  1842.             HLock((Handle)vers);
  1843.             ParamText((**vers).versionStr,NULL,NULL,NULL);
  1844.             ReleaseResource((Handle)vers);
  1845.         } else
  1846.             ParamText("\p????",NULL,NULL,NULL);
  1847.         
  1848.         ShowWindow(aboutScreen);
  1849.         SelectWindow(aboutScreen);
  1850.         DrawDialog(aboutScreen);
  1851.         SetPort(aboutScreen);
  1852.         if (pictHandle)
  1853.         {
  1854.             HLock((Handle)pictHandle);
  1855.             DrawPicture(pictHandle, &itemRect);
  1856.             HUnlock((Handle)pictHandle);
  1857.             ReleaseResource((Handle)pictHandle);
  1858.         }
  1859.  
  1860.         ValidRect(&aboutScreen->portRect);
  1861.     }
  1862.     return aboutScreen;
  1863. }
  1864.